﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
using System.IO;
using System.Text;
using PetroMentor.Service.Common;
using System.Reflection;
using PetroMentor.Service.Entities;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;


namespace PetroMentor.Service.Manager
{
    /// <summary>
    /// 序列化管理器
    /// </summary>
    public class SerializeManager
    {

        public static string SerializeQueryEntities(string module, int pagenumber, int pagesize, string whereclause,string orderby)
        { 
            int start = ((pagenumber-1) * pagesize) +1;
            int end = pagenumber * pagesize;

            string sqlCount = string.Format("select count(*) FROM {0} where {1}",module,whereclause);

            string sql = string.Format("SELECT q.*  FROM (SELECT s.*, rownum seq FROM (SELECT t.* FROM {0} t where {1} order by {4}  ) s) q WHERE q.seq >= {2} AND  q.seq <= {3}",
                module,whereclause,start,end,orderby);

            Assembly ass = Assembly.Load("PetroMentor.Service");
            object instance = ass.CreateInstance(string.Format("PetroMentor.Service.{0}", module));
            Type type = instance.GetType();

           Type genericClass = typeof(EntitiesManager<>);
           // MakeGenericType is badly named
           Type constructedClass = genericClass.MakeGenericType(type);

           object created = Activator.CreateInstance(constructedClass);
           MethodInfo curMethod = constructedClass.GetMethod("SelectBySql");
           object result = curMethod.Invoke(created, new object[] { sql }); //constructedClass.GetMethod("SelectBySql").Invoke(created, sql);
           MethodInfo resultMethod = constructedClass.GetMethod("SelectResultCount");
           object resultcount = resultMethod.Invoke(created, new object[] { sqlCount });

           Type genericResultClass = typeof(CommonQueryInfo<>);
           Type constructedResultClass = genericResultClass.MakeGenericType(type);
           
           object queryresultobj = Activator.CreateInstance(constructedResultClass);
           MethodInfo initMethod = constructedResultClass.GetMethod("Init");
           initMethod.Invoke(queryresultobj, new object[] { resultcount, pagenumber,pagesize, result });
           string strTemp = ObjectToJson(queryresultobj);
           return strTemp;
        
        }


        public static string SerializeSaveEntity<T1,T2>(CommonSaveInfo<T1, T2> saveinfo)
        {
            try
            {
                #region 构造Json 反序列化对象
                Assembly ass = Assembly.Load("PetroMentor.Service");
                object module_instance = ass.CreateInstance(string.Format("PetroMentor.Service.{0}", saveinfo.SaveObjectName));
                object attmodule_instance = ass.CreateInstance(string.Format("PetroMentor.Service.{0}", saveinfo.AttachmentName));
                Type module_type = module_instance.GetType();
                Type attmodule_type = attmodule_instance.GetType();

                Type l = typeof(List<>);
                Type ll = l.MakeGenericType(attmodule_type);




                object module_created = Activator.CreateInstance(module_type);
                object attm_created = Activator.CreateInstance(ll);

                object moduleaddobj = saveinfo.SaveObject;//JsonConvert.DeserializeObject<T_WHYL_AQXS>(modulecontent, new JavaScriptDateTimeConverter());
                object attmaddobj = saveinfo.Attachments;// JsonConvert.DeserializeObject<List<T_WHYL_ATTACHMENT>>(attcontent, new JavaScriptDateTimeConverter());

                //object moduleaddobj = JsonDeserialize(modulecontent, module_created);
                //object attmaddobj = JsonDeserialize(attcontent, attm_created);

                #endregion


                Type managerClass = typeof(EntitiesManager<>);
                // MakeGenericType is badly named
                Type constructedmanager = managerClass.MakeGenericType(module_type);
                object createdmanager = Activator.CreateInstance(constructedmanager);
                MethodInfo curMethod;
                if (saveinfo.OP_TYPE == Consts.OP_CREATE)
                {
                    curMethod = constructedmanager.GetMethod("Add", new Type[] { module_type });
                }
                else
                {
                    curMethod = constructedmanager.GetMethod("Update", new Type[] { module_type });
                }
                object moduleresult = curMethod.Invoke(createdmanager, new object[] { moduleaddobj });



                Type attmanagerClass = typeof(EntitiesManager<>);

                // MakeGenericType is badly named
                Type attmanager = attmanagerClass.MakeGenericType(attmodule_type);
                object attObjmanager = Activator.CreateInstance(attmanager);

                Type attlst = typeof(IList<>);
                Type attlstManager = attlst.MakeGenericType(attmodule_type);
                MethodInfo attmethod;
                if (saveinfo.OP_TYPE == Consts.OP_CREATE)
                {
                    attmethod = attmanager.GetMethod("Add", new Type[] { attlstManager });
                }
                else
                {
                    attmethod = attmanager.GetMethod("Update", new Type[] { attlstManager });
                }



                object attresult = attmethod.Invoke(attObjmanager, new object[] { attmaddobj });



                SaveStateInfo info = new SaveStateInfo() { IsSuccess = true };

                return ObjectToJson(info);
            }
            catch (Exception ex)
            {
                SaveStateInfo info = new SaveStateInfo() { IsSuccess = false, ErrorInfo = ex.Message };

                return ObjectToJson(info);
            }
            
        }


        public static string DeleteByIds(string module, string attachmentmodule, string ids)
        {
            try
            {
                Assembly ass = Assembly.Load("PetroMentor.Service");
                object module_instance = ass.CreateInstance(string.Format("PetroMentor.Service.{0}", module));
                object attmodule_instance = ass.CreateInstance(string.Format("PetroMentor.Service.{0}", attachmentmodule));
                Type module_type = module_instance.GetType();
                Type attmodule_type = attmodule_instance.GetType();

                object module_created = Activator.CreateInstance(module_type);
                object attm_created = Activator.CreateInstance(attmodule_type);

                Type managerClass = typeof(EntitiesManager<>);
                // MakeGenericType is badly named
                Type constructedmanager = managerClass.MakeGenericType(module_type);
                object createdmanager = Activator.CreateInstance(constructedmanager);
                MethodInfo curMethod;
                curMethod = constructedmanager.GetMethod("Delete", new Type[] { typeof(string), typeof(string), typeof(string) });

                curMethod.Invoke(createdmanager, new object[] { module, attachmentmodule, ids });

                SaveStateInfo info = new SaveStateInfo() { IsSuccess = true };

                return ObjectToJson(info);
            }
            catch(Exception ex) {

                SaveStateInfo info = new SaveStateInfo() { IsSuccess = false, ErrorInfo = ex.Message };

                return ObjectToJson(info);
            
            }
        }

        public static string SerializeSaveEntity(string module, string attachmentmodule, string modulecontent, string attcontent,string optype)
        {
            try
            {
                #region 构造Json 反序列化对象
                Assembly ass = Assembly.Load("PetroMentor.Service");
                object module_instance = ass.CreateInstance(string.Format("PetroMentor.Service.{0}", module));
                object attmodule_instance = ass.CreateInstance(string.Format("PetroMentor.Service.{0}", attachmentmodule));
                Type module_type = module_instance.GetType();
                Type attmodule_type = attmodule_instance.GetType();

                Type l = typeof(List<>);
                Type ll = l.MakeGenericType(attmodule_type);
               



                object module_created = Activator.CreateInstance(module_type);
                object attm_created = Activator.CreateInstance(ll);

                object moduleaddobj = JsonConvert.DeserializeObject<T_WHYL_AQXS>(modulecontent,new JavaScriptDateTimeConverter());
                object attmaddobj = JsonConvert.DeserializeObject<List<T_WHYL_ATTACHMENT>>(attcontent,new JavaScriptDateTimeConverter());

                //object moduleaddobj = JsonDeserialize(modulecontent, module_created);
                //object attmaddobj = JsonDeserialize(attcontent, attm_created);

                #endregion


                Type managerClass = typeof(EntitiesManager<>);
                               // MakeGenericType is badly named
                Type constructedmanager = managerClass.MakeGenericType(module_type);
                object createdmanager = Activator.CreateInstance(constructedmanager);
                MethodInfo curMethod;
                if (optype == Consts.OP_CREATE)
                {
                    curMethod = constructedmanager.GetMethod("Add", new Type[] { module_type });
                }
                else
                {
                    curMethod = constructedmanager.GetMethod("Update", new Type[] { module_type });
                }
                object moduleresult = curMethod.Invoke(createdmanager, new object[] { moduleaddobj });



                Type attmanagerClass = typeof(EntitiesManager<>);

                // MakeGenericType is badly named
                Type attmanager = attmanagerClass.MakeGenericType(attmodule_type);
                object attObjmanager = Activator.CreateInstance(attmanager);

                Type attlst = typeof(IList<>);
                Type attlstManager = attlst.MakeGenericType(attmodule_type);
                MethodInfo attmethod ;
                if (optype == Consts.OP_CREATE)
                {
                    attmethod = attmanager.GetMethod("Add", new Type[] { attlstManager });
                }
                else
                {
                    attmethod = attmanager.GetMethod("Update", new Type[] { attlstManager });
                }



                object attresult = attmethod.Invoke(attObjmanager, new object[] { attmaddobj });



                SaveStateInfo info = new SaveStateInfo() { IsSuccess = true };

                return ObjectToJson(info);
            }
            catch (Exception ex)
            {
                SaveStateInfo info = new SaveStateInfo() { IsSuccess = false, ErrorInfo = ex.Message };

                return ObjectToJson(info);
            }
            
        }

        //public static string SelectEntitiesResult(string module, int pagenumber, int pagesize, string whereclause)
        //{
        //    string str = string.Empty;
        //    EntitiesManager<T_WHYL_AQXS> manager = new EntitiesManager<T_WHYL_AQXS>();
        //    List<T_WHYL_AQXS> lst = manager.Select(" from T_WHYL_AQXS").ToList();
        //    str = Object2string<List<T_WHYL_AQXS>>(lst);
        //    return str;
        //}

        public static string Object2string<T>(T t)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(ms, t);
                ms.Seek(0, SeekOrigin.Begin);
                using (StreamReader reader = new StreamReader(ms, Encoding.UTF8))
                {
                    return reader.ReadToEnd();
                }
            }
        }


        public static T JsonDeserialize<T>(string jsonString)
        {
            //将"yyyy-MM-dd HH:mm:ss"格式的字符串转为"//Date(1294499956278+0800)//"格式    
            string p = @"/d{4}-/d{2}-/d{2}/s/d{2}:/d{2}:/d{2}";
            MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertDateStringToJsonDate);
            Regex reg = new Regex(p);
            jsonString = reg.Replace(jsonString, matchEvaluator);
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
            T obj = (T)ser.ReadObject(ms);
            return obj;
        }

        public static object JsonDeserialize(string jsonString,object obje)
        {
            //将"yyyy-MM-dd HH:mm:ss"格式的字符串转为"//Date(1294499956278+0800)//"格式    
            string p = @"/d{4}-/d{2}-/d{2}/s/d{2}:/d{2}:/d{2}";
            MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertDateStringToJsonDate);
            Regex reg = new Regex(p);
            jsonString = reg.Replace(jsonString, matchEvaluator);
            DataContractJsonSerializer ser = new DataContractJsonSerializer(obje.GetType());
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));

            return ser.ReadObject(ms);
        }

        private static string ConvertDateStringToJsonDate(Match m)
        {
            string result = string.Empty;
            DateTime dt = DateTime.Parse(m.Groups[0].Value);
            dt = dt.ToUniversalTime();
            TimeSpan ts = dt - DateTime.Parse("1970-01-01");
            result = string.Format("//Date({0}+0800)//", ts.TotalMilliseconds);
            return result;
        }    

        public static object JsonToObject(string jsonString, object obj)
        {

            System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());

            System.IO.MemoryStream mStream = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(jsonString));

            return serializer.ReadObject(mStream);

        }

        public static string ObjectToJson(object obj)
        {
            System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());

            string szJson = "";

            //序列化

            using (MemoryStream stream = new MemoryStream())
            {
                serializer.WriteObject(stream, obj);
                szJson = Encoding.UTF8.GetString(stream.ToArray());
            }
            return szJson;

        }

        public static byte[] ObjectToByte(object obj)
        {
            BinaryFormatter se = new BinaryFormatter();
            MemoryStream memStream = new MemoryStream();
            se.Serialize(memStream, obj);
            byte[] bobj = memStream.ToArray();
            memStream.Close();
            return bobj;
        }

        public static string StreamToString(Stream stream)
        {
            stream.Position = 0;
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                return reader.ReadToEnd();
            }
        }


    }

    
}